package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.entity.Category;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    SpuService spuService;

    @Autowired
    SpuDetailService spuDetailService;

    @Autowired
    SkuService skuService;

    @Autowired
    AmqpTemplate amqpTemplate;

    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        //1.健壮性判断
        //取最大值Math.max()
        int current = Math.max(page, 1);
        int size = Math.max(rows, 5);
        //查出id和商品名称
        Page<Spu> pagelist = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                .page(new Page<Spu>(current, size));
        //查询spu的分类和品牌名称
        List<SpuDTO> dtoList = SpuDTO.convertEntityList(pagelist.getRecords());
        for (SpuDTO spuDTO : dtoList) {
            // 查询spu的分类和品牌的名称
            handleCategoryAndBrandName(spuDTO);
        }

        return new PageDTO<SpuDTO>(pagelist.getTotal(), pagelist.getPages(), dtoList);
    }


    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        // 根据品牌id查询品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand != null) {
            spuDTO.setBrandName(brand.getName());
        }

        // 根据三级分类id查询分类集合
        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());
        if (CollectionUtils.isEmpty(categories) == false) {
            //取出分类的名称，使用流的方式拼接起来
            String names = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }


    //商品新增
    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
        //新增spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean b1 = save(spu);
        if (b1 == false) {
            throw new LyException(500, "spu新增失败");
        }

        //新增SpuDetail
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());//设置回显id
        boolean b2 = spuDetailService.save(spuDetail);
        if (b2 == false) {
            throw new LyException(500, "SpuDetail新增失败");
        }

        //新增sku
        List<Sku> skuList = spuDTO.getSkus().stream()
                .map(skuDTO -> {
                    Sku sku = skuDTO.toEntity(Sku.class);
                    sku.setSaleable(false);
                    sku.setSpuId(spu.getId());
                    return sku;
                })
                .collect(Collectors.toList());
        boolean b3 = skuService.saveBatch(skuList);
        if (b3 == false) {
            throw new LyException(500, "sku新增失败");
        }
    }

    @Transactional
    @Override
    public SpuDTO queryGoodsById(Long id) {

        //查spu信息
        Spu spu = getById(id);
        SpuDTO spuDTO = new SpuDTO(spu);

        System.out.println("id = " + id);
        //查询商品详情
        SpuDetail spuDetail = spuDetailService.getById(id);
        spuDTO.setSpuDetail(spuDetail.toDTO(SpuDetailDTO.class));
        //spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));//老师代码

        //查询sku
        List<Sku> skuList = skuService.query()
                .eq("spu_id", id)
                .list();
        List<SkuDTO> skuDTOList = SkuDTO.convertEntityList(skuList);
        spuDTO.setSkus(skuDTOList);

        //设置商品的分类和品牌信息
        handleCategoryAndBrandName(spuDTO);

        return spuDTO;
    }

    @Transactional
    @Override
    public void updateGoods(SpuDTO spuDTO) {
        //跟新基础信息
        if (spuDTO.getId() != null) {
            boolean save = saveOrUpdate(spuDTO.toEntity(Spu.class));
            if (save == false) {
                throw new LyException(500, "修改spu失败");
            }
        }

        //更新商品详情
        if (spuDTO.getSpuDetail() != null && spuDTO.getSpuDetail().getSpuId() != null) {
            boolean saveOrUpdate = spuDetailService.saveOrUpdate(spuDTO.getSpuDetail().toEntity(SpuDetail.class));
            if (saveOrUpdate == false) {
                throw new LyException(500, "修改spuDetail失败");
            }
        }


        //修改sku
        //三种
        List<SkuDTO> skus = spuDTO.getSkus();
        //不加会空指针错误
        if (CollectionUtils.isEmpty(skus)) {
            return;
        }
        //第一种：带saleable:false，是删除的
        Map<Boolean, List<Sku>> skulist1 = skus.stream().map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
        //没有删除时候空指针.collect(Collectors.groupingBy(sku -> sku.getSaleable() == false));
        // 因为这个属性不是null就是false，下面List<Sku> list = skulist1.get(true);就会出错
        //是空为真，不为空为假
        if (skulist1.get(false)!=null) {
            List<Sku> list = skulist1.get(false);
            List<Long> collect = list.stream().map(Sku::getId)
                    .collect(Collectors.toList());
            skuService.removeByIds(collect);
        }

        //第二种：没有id，是新增的
        Map<Boolean, List<Sku>> skulist2 = skus.stream().map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getId() == null));
        if (skulist2.get(true)!=null) {
            List<Sku> skus1 = skulist2.get(true);
            skuService.saveBatch(skus1);
        }

        //第三种: 有id，没有saleable，是修改的
        Map<Boolean, List<Sku>> skulist3 = skus.stream().map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getId() != null && sku.getSaleable() == null));

        if (skulist3.get(true)!=null) {//假如没有要修改的直接运行下面会报空指针异常
            List<Sku> skus2 = skulist3.get(true);
            skuService.updateBatchById(skus2);
        }
    }

    @Override
    public void updateSaleable(Long id, Boolean saleable) {
        // 1.更新SPU
        //Spu spu = new Spu();
        //spu.setId(id);
        //spu.setSaleable(saleable);
        //boolean success = updateById(spu);
        //链式编程，一行更比四行强
        boolean success = update().set("saleable", saleable).eq("id", id).update();
        if (success == false) {
            throw new LyException(500, "更新失败");
        }


        // 2.更新sku,有冗余保存
        success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (success == false) {
            throw new LyException(500, "更新失败");
        }
        // 3.发送MQ消息
        String routingKey = saleable ? MQConstants.RoutingKeyConstants.ITEM_UP_KEY : MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME, routingKey, id);

    }
}